#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <assert.h>
#include "aimage.h"
#include "aimage_utils.h"
#include "aimage_ppm.h"

int main( int argc, const char *argv[] )
{
	AIMAGE image;
	int i;
	AIMAGE orig_image;
	int width, height;
	float xo, yo, ro;
	const char *last_img;
	const char *curr_img;

	const rlim_t kStackSize = 128 * 1024L * 1024L;
	struct rlimit rl;

	int result;
	result = getrlimit( RLIMIT_STACK, &rl );
	if ( result == 0 )
	{
		fprintf( stderr, "Stack size is %dK\n", ((int) ( rl.rlim_cur / 1024L )));
		if ( rl.rlim_cur < kStackSize )
		{
			rl.rlim_cur = kStackSize;
			result = setrlimit( RLIMIT_STACK, &rl );
			if ( result == 0 )
			{
				fprintf( stderr, "Stack size set to %dK\n", ((int) (rl.rlim_cur / 1024L )));
			}
		}
	}

	//setrlimit( RLIMIT_STACK, &rl );

	if ( argc <= 1 )
	{
		fprintf(stderr, "%s file1 file2...\n", argv[0] );
		exit( 1 );
	}

	SOLAR_FRAMES_ALIGNMENT align_data;
	align_data.read_solar_align_data( argv[1] );

	ASTAR_FIELD stars[ 2 ];
	ASTAR_FIELD *curr_stars = NULL;
	ASTAR_FIELD *last_stars = NULL;

	for ( i = 2; i < argc; ++i )
	{
		float xc, yc, rad;
		srand( 1 );
		AIMAGE_PPM_UTILS::load( image, argv[i] );
		image.get_dim( width, height );

		curr_stars = &( stars[ i % 2 ] );
		curr_img = argv[ i ]; 

		orig_image.alloc_image( width, height );
		AIU::cls( orig_image, 0, 0, 0 );

		orig_image.mask_for_sunspots( image, .9, 20 );

		align_data.lookup_alignment( argv[i], xc, yc, rad );

		APIXEL blue, black, red, green;
		blue.r = 0; blue.g = 0; blue.b = FULL_INT;
		black.r = 0; black.g = 0; black.b = 0;
		green.r = 0; green.g = FULL_INT; green.b = 0;
		red.r = FULL_INT; red.g = 0; red.b = 0;

		orig_image.circle( xc, yc, rad * .95, blue, false );

		AFLOOD_DATA fdata;

		fdata.rs = 0; fdata.gs = 0; fdata.bs = FULL_INT;
		fdata.rd = 0, fdata.gd = 0, fdata.bd = FULL_INT;
		fdata.fill_to_border_mode = true;

		orig_image.floodfill( 100, 100, fdata );

		fdata.bd = 0; fdata.fill_to_border_mode = false;
		orig_image.floodfill( 100, 100, fdata );

		ASTAR_FIELD stars_with_venus;

		fprintf(stderr,"Finding Stars\n");

		orig_image.starfind( .2, stars_with_venus );

		fprintf(stderr,"Masking Out Venus\n");

		stars_with_venus.filter_by_pixels( 2000, false );
		
		assert( stars_with_venus.get_num_stars() <= 1 );
		if ( stars_with_venus.get_num_stars() == 1 )
		{
			const ASTAR_DATA &venus = stars_with_venus.get_star( 0 );
			orig_image.circle( venus.xc, venus.yc, 70.0f, red, false );  

			fdata.rs = FULL_INT; fdata.gs = 0; fdata.bs = 0;
			fdata.rd = FULL_INT, fdata.gd = 0, fdata.bd = 0;
			fdata.fill_to_border_mode = true;

			orig_image.floodfill( venus.xc, venus.yc, fdata );

			fdata.rd = 0; fdata.fill_to_border_mode = false;
			orig_image.floodfill( venus.xc, venus.yc, fdata );
		}


		fprintf(stderr,"Re Masking\n");
		orig_image.makemask( 0.05f );

		ASTAR_FIELD stars_without_venus;
		orig_image.starfind( .2, *curr_stars );

		fprintf(stderr,"Drawing Stars\n");
		float error = 0.0f;

		if ( last_stars != NULL )
		{

			float curr_xc, curr_yc, curr_rad;
			float last_xc, last_yc, last_rad;

			align_data.lookup_alignment( curr_img, curr_xc, curr_yc, curr_rad );
			align_data.lookup_alignment( last_img, last_xc, last_yc, last_rad );

			ASTAR_TRANSFORM t;
			ASTAR_TRANSFORM new_t;
			t.xo = curr_xc - last_xc;
			t.yo = curr_yc - last_yc;
			t.angle = 0;

			new_t = curr_stars->synch_fields( *last_stars, t );
			new_t = t;

			float d_of_record;
			d_of_record = last_stars->avg_distance( *curr_stars, new_t );
			error = d_of_record;

			align_data.lookup_alignment( last_img, xo, yo, ro );
			xo += new_t.xo;
			yo += new_t.yo;

			fprintf(stderr, "Distance %g Adjust %g %g\n", 
					d_of_record,
					new_t.xo - t.xo, 
					new_t.yo - t.yo
			);
			//t.angle = 0.0f;

#define DRAW
#ifdef DRAW
			AIMAGE i0, i1, it, alpha;
			
			AIMAGE_PPM_UTILS::load( i0, argv[ i-1 ] );
			AIMAGE_PPM_UTILS::load( i1, argv[ i ] );

			alpha.alloc_image( width, height );
			AIU::cls( alpha, 0, 0, 0 );

			it.alloc_image( width, height );

			ASTAR_TRANSFORM tt;
			tt.xo = -new_t.xo;
			tt.yo = -new_t.yo;
			tt.angle = -new_t.angle;

			i0.scale_by_256();
			AIU::cls( it, 0, 0, 0 );
			it.rotate_and_add( alpha, i0, tt );
			it.adjust_by_alpha( alpha );
			it.diff( i1 );

			//i1.writeppm("differ/old.ppm", false);
			//it.writeppm("differ/new.ppm", false);

			//return 0;

			//ASTAR_FIELD transform_stars;
			//transform_stars.transform( *last_stars, new_t );
			//it.drawstars( *curr_stars, red );
			//it.drawstars( transform_stars, green );
			AIMAGE_PPM_UTILS::save( it, "stdout", false );
			return 0;
#endif
		}
		else
		{
			align_data.lookup_alignment( argv[ i ], xo, yo, ro );
			last_stars = curr_stars;
			last_img = curr_img;
		}

#ifndef DRAW
		printf("%s X %g Y %g R %g Error %g\n", argv[i], xo, yo, ro, error );
#endif

		last_stars->top_x_by_pixels( 20 );
	}
}

